package win.devhu.playground

import freemarker.cache.ClassTemplateLoader
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.application.log
import io.ktor.features.*
import io.ktor.freemarker.FreeMarker
import io.ktor.freemarker.FreeMarkerContent
import io.ktor.gson.gson
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.http.content.*
import io.ktor.http.withCharset
import io.ktor.response.respond
import io.ktor.response.respondRedirect
import io.ktor.response.respondText
import io.ktor.routing.Routing
import io.ktor.routing.get
import io.ktor.routing.routing
import org.slf4j.event.Level
import java.text.DateFormat
import java.time.LocalDate

/**
 * @Author: Devhu
 * @Date: 2018/9/22
 * @Description: Learn Ktolin web framework Ktor
 */

//val LOG: Logger = LoggerFactory.getLogger("Main.kt")  //ktor application has a log property

//Extract Module
fun Application.main(){
    log.debug("DevelopmentEngine Modle Main class is 'io.ktor.server.netty.DevelopmentEngine' do not need main() anymore")

    install(ConditionalHeaders) //avoid sending content if the client already has the same content
    install(DefaultHeaders) {
        header("X-Developer", "Devhu") // will send this header with each response
    }
    install(CallLogging){
        level = Level.INFO
    }
    install(ContentNegotiation) {
        gson {
            setDateFormat(DateFormat.LONG)
            setPrettyPrinting()
        }
    }
    install(FreeMarker) {
        templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates")
    }
    install(StatusPages){
        exception<Throwable> { cause ->
            call.respond(HttpStatusCode.InternalServerError)
            log.error("$cause")
        }
        status(HttpStatusCode.NotFound) {
            call.respond(TextContent("${it.value} ${it.description}", ContentType.Text.Plain.withCharset(Charsets.UTF_8), it))
        }
    }

    routing {
        static("static") {
            staticBasePackage = resources("static").toString() //very important!! set resources file base path
            resources("css")    //use url: static/css/xxx.css
            resources("js")     //use url: static/js/xxx.js
            resource("*.png","*.jpg")       //use url: static/xxx.png
        }
        root()
    }
}

data class Model(val name: String, val items: List<Item>,
                 val date: LocalDate = LocalDate.of(2018, 9, 23))
data class Item(val key: String, val value: String)
data class User(val name: String, val email: String)    //for freemarker template

val model = Model("购物清单", listOf(Item("fruit", "苹果"), Item("vegetables", "西红柿")))

//Extract route
fun Routing.root(){
    get("/") {
        call.respondRedirect("/freemarker")
    }
    get("/health_check") {
        // Check databases/other services.
        call.respondText("OK")
    }
    get("/demo"){
        call.respondText("Hello,Devhu! atuoload")
    }
    //simple for gson
    get("/v1") {
        call.respond(model)
    }
    get("/v1/item/{key}") {
        val item = model.items.firstOrNull { it.key == call.parameters["key"] }
        if (item == null)
            call.respond(HttpStatusCode.NotFound)
        else
            call.respond(item)
    }

    //simple for freemarker
    get("/freemarker") {
        val user = User("胡予", "devhu@foxmail.com");
        call.respond(FreeMarkerContent("index.ftl", mapOf("user" to user,"model" to model), "e"))
    }
}